package zl.applet.oldsnakey;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;

import javax.swing.JOptionPane;
import javax.swing.JPanel;

//枚举、表示方向
enum Orient
{
	up,down,left,right   //上、下、左、右
}

//枚举、表示蛇的状态
enum SnakeState
{
	first,start,pause,stop   //未开始、开始、暂停、停止
}

public class MyPanel extends JPanel implements KeyListener,Runnable
{
	private static final long serialVersionUID = 1L;
	private SnakeState state;   //状态
	private int food;   //食物（蛇）的尺寸
	private int foodX;   //食物的X坐标
	private int foodY;   //食物的Y坐标
	private int headX;   //蛇头部X坐标
	private int headY;   //蛇头部Y坐标
	private Orient oldOrient;  //原先方向    
	private Orient newOrient;  //新方向	
	private String[] turn = new String[100];  //保存蛇的最近行动路径
	private int snake;   //蛇吃的食物
	private int count;   //蛇运动的次数
	private Random random;   //声明产生随机数类
	private int speed;    //蛇的速度
	private Thread paintThread;   //声明线程
	private String message;   //消息
	private OldSnakey os;   //窗体对象

	public MyPanel(OldSnakey os)  //构造
	{	
		this.os = os;  //本对象所属窗体
		this.state = SnakeState.first;   //状态、枚举类型
		this.initial();   //初始化
		this.paintThread = new Thread(this);  //实例化线程
		this.setBackground(Color.GREEN);   //设置背景色
	}

	public void initial()  //初始化
	{
		this.addKeyListener(this);   //添加事件监听器
		this.food = 10;   //食物尺寸
		this.snake = 1;   //蛇吃的食物
		this.count = 0;   //蛇运动的次数
		this.turn = new String[100];  //蛇最近100次运动轨迹
		this.oldOrient = Orient.up;   //蛇的原先运动方向
		this.newOrient = Orient.up;	  //蛇的现在运动方向
		this.random = new Random();   
		if(this.state == SnakeState.first)  //如果状态是第一次
		{
			//则食物和舌头不可见
			this.headX = -this.food;
			this.headY = -this.food;
			this.foodX = -this.food;
			this.foodY = -this.food;
		}
		else
		{
			//舌头默认在最下方
			this.headX = (int)(this.getWidth() / 2 - this.food / 2);
			this.headY = this.getHeight();
			//随机产生食物位置
			this.foodX = this.random.nextInt(this.headX)/this.food*this.food;
			this.foodY = this.random.nextInt(this.headY)/this.food*this.food;
		}
	}

	public SnakeState getState()
	{
		//获取蛇的状态
		return this.state;
	}

	public void setState(SnakeState state)
	{
		//设置蛇的状态
		this.state = state;
	}

	public void setState(SnakeState state,String message)
	{
		//设置带消息的蛇的状态、通常给定
		this.state = state;
		this.message = message;
	}

	public void start(int speed)
	{
		this.speed = speed;
		//System.out.println(this.getWidth());
		//System.out.println(this.getHeight());
		this.headX = (int)(this.getWidth() / 2 - this.food / 2);
		this.headY = this.getHeight();
		//System.out.println(this.headX);
		//System.out.println(this.headY);
		this.foodX = this.random.nextInt(this.headX)/this.food*this.food;
		this.foodY = this.random.nextInt(this.headY)/this.food*this.food;
		if(this.paintThread.getState() == Thread.State.NEW)
			this.paintThread.start();
	}

	public void paint(Graphics g)
	{
		super.paint(g);
		this.turn[this.count] = this.headX + "Z" + this.headY;  //记录每次运动的X Y坐标
		//画食物
		g.setColor(Color.BLACK);
		g.fillOval(this.foodX,this.foodY,this.food,this.food);
		//画蛇头 
		g.setColor(Color.BLUE);
		g.fillRect(this.headX,this.headY,this.food,this.food);
		for(int i = 1; i < this.snake; i++)
		{
			int j = this.count - i;
			if(j < 0)
				j = j + 100;
			String[] temp = this.turn[j].split("Z");
			if(Integer.parseInt(temp[0]) == this.headX && Integer.parseInt(temp[1]) == this.headY)
			{
				g.setColor(Color.BLUE);
				this.setState(SnakeState.stop,"撞到自己、");
			}
			else
				g.setColor(Color.RED);
			g.fillRect(Integer.parseInt(temp[0]),Integer.parseInt(temp[1]),this.food,this.food);
		}
	}

	//实现Runnable接口定义的方法
	public void run()
	{
		synchronized(this){
		while(true)
		{
			this.count++;  //记录蛇的每一次运动
			if(this.count >= 100)
				this.count = 0;
			//此 if-else 判断蛇的新方向和就方向是否是垂直方向。如是垂直方向。则改变蛇的运动方向
			if((this.oldOrient == Orient.down || this.oldOrient == Orient.up) && (this.newOrient == Orient.left || this.newOrient == Orient.right))
				this.oldOrient = this.newOrient;
			else if((this.oldOrient == Orient.left || this.oldOrient == Orient.right) && (this.newOrient == Orient.up || this.newOrient == Orient.down))
				this.oldOrient = this.newOrient;
			switch(this.oldOrient)   //判断蛇的方向
			{
				case up:  //上
					headY -= this.food;
					break;
				case down:  //下
					headY += this.food;
					break; 
				case left:  //左
					headX -= this.food;
					break;
				case right:  //右
					headX += this.food;
					break;
			}
			if(this.headX < 0 || this.headX > this.getWidth() - this.food || 
				this.headY < 0 || this.headY > this.getHeight() - this.food)
			{
				this.setState(SnakeState.stop,"撞到墙、");
			}
			else
				this.repaint();   //调用此方法、系统自动调用重写后的paint方法
			if(this.headX == this.foodX && this.headY == this.foodY)
			{
				this.snake++;   //记录蛇所吃食物的个数
				if(this.speed > 100)
					this.speed-=10;     //每吃到一个食物。速度加快
				//重新随机生成食物
				this.foodX = this.random.nextInt(300)/this.food*this.food;
				this.foodY = this.random.nextInt(400)/this.food*this.food;
				this.os.setScore((400-speed) * this.snake);   //改变所属窗体显示的分数
			}
			try
			{
				Thread.sleep(this.speed);  //线程睡眠
			}
			catch (Exception e)
			{ 
				//如有异常则跑出
				e.printStackTrace();
			}
			while(this.state == SnakeState.pause || this.state == SnakeState.stop)
			{
				
				if(this.state == SnakeState.stop)
				{
					this.os.setRadioButton(true);
					if(this.message != null)
					{
						//显示蛇停止运动的原因
						JOptionPane.showMessageDialog(this,this.message,"消息",JOptionPane.INFORMATION_MESSAGE);
						this.os.showResult((400-speed) * this.snake);  //显示结果
					}
					this.message = null;
					this.initial();   //初始化
				}
				try
				{
					Thread.sleep(100);  //如果是暂停和停止状态、则死循环
				}
				catch (Exception e)
				{
					e.printStackTrace();
				}
			}
		}
		}
	}

	//实现KeyListener接口定义的方法

	//键盘按下时响应
	public void keyPressed(KeyEvent e)
	{
		if(e.getKeyCode() == KeyEvent.VK_UP)
			this.newOrient = Orient.up;
		else if(e.getKeyCode() == KeyEvent.VK_DOWN)
			this.newOrient = Orient.down;
		else if(e.getKeyCode() == KeyEvent.VK_LEFT)
			this.newOrient = Orient.left;
		else if(e.getKeyCode() == KeyEvent.VK_RIGHT)
			this.newOrient = Orient.right;
	}

	//操作键盘编辑区时响应
	public void keyTyped(KeyEvent e){}
	//键盘释放时响应、、
	public void keyReleased(KeyEvent e){}
}